<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Application
 * @package    Controller
 * @copyright  Copyright (c) 2007,2008 Rob Allen
 * @license    http://framework.zend.com/license/new-bsd  New BSD License
 */

/** Zend_Controller_Action_Helper_Abstract */
require_once 'Zend/Controller/Action/Helper/Abstract.php';


/**
 * ACL integration
 *
 * Places_Controller_Action_Helper_Acl provides ACL support to a 
 * controller.
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @package    Controller
 * @subpackage Controller_Action
 * @copyright  Copyright (c) 2007,2008 Rob Allen
 * @license    http://framework.zend.com/license/new-bsd  New BSD License
 */
class Fkb_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract
{

    /**
     * @var Zend_Auth
     */
    protected $_auth;

    /**
     * @var Zend_Acl
     */
    protected $_acl;

    /**
     * @var Zend_Controller_Action
     */
    protected $_action;

    /**
     * Optionally set view object and options.
     *
     * @param  Zend_View_Interface $view
     * @param  array $options
     * @return void
     */
    public function __construct(Zend_View_Interface $view = null, array $options = array())
    {
        $this->_auth = Zend_Auth::getInstance();
        $this->_acl = $options['acl'];
    }

    /**
     * Hook into action controller initialization
     *
     * @return void
     */
    public function init()
    {
        $this->_action = $this->getActionController();
    }

    /**
     * Hook into action controller preDispatch() workflow.
     *
     * @return void
     */
    public function preDispatch()
    {
        $role = 'guest';
        if ($this->_auth->hasIdentity()) {
            $user = $this->_auth->getIdentity();
            
            if(is_array($user)) {
                $role = $user['role'];
            }
        }

        $request = $this->_action->getRequest();
        $resource = $request->getActionName();

        if (!$this->_acl->has($resource)) {
            $resource = null;
        }

        if (!$this->_acl->isAllowed($role, $resource)) {
	    $request->setControllerName('auth');
	    $request->setDispatched(false);
	    
	    $action = $this->_auth->hasIdentity() 
		    ? 'access-violation' 
		    : 'login';
	    $request->setActionName($action);
        }
    }

    /**
     * Proxy to the underlying Zend_Acl's allow()
     *
     * We use the controller's name as the resource and the
     * action name(s) as the privilege(s)
     *
     * @param  Zend_Acl_Role_Interface|string|array     $roles
     * @param  string|array                             $actions
     * @uses   Zend_Acl::setRule()
     * @return Places_Controller_Action_Helper_Acl Provides a fluent interface
     */
    public function allow($roles = null, $resources = null)
    {
	if(!is_array($resources))
	{
	    $resources = array($resources);
	}
	
	foreach($resources as $resource)
	{
	    if($resource !== null && !$this->_acl->has($resource)) {
		$this->_acl->addResource($resource);
	    }

	    $this->_acl->allow($roles, $resource);
	}
        
        return $this;
    }

    /**
     * Proxy to the underlying Zend_Acl's deny()
     *
     * We use the controller's name as the resource and the
     * action name(s) as the privilege(s)
     *
     * @param  Zend_Acl_Role_Interface|string|array     $roles
     * @param  string|array                             $actions
     * @uses   Zend_Acl::setRule()
     * @return Places_Controller_Action_Helper_Acl Provides a fluent interface
     */
    public function deny($roles, $resource)
    {
        $this->_acl->deny($roles, $resource);
        return $this;
    }

}
